# Django предлагает разнообразный набор встроенных шаблонных тегов, 
# таких как % if % или % block %. Но можно разрабатывать свои:
# Реализация конкретно-прикладных шаблонных тегов
# Создание простого шаблонного тега
from django import template
from ..models import Post, Comment
from django.db.models import Count # Создание шаблонного тега, возвращающего набор запросов
from django.utils.safestring import mark_safe # для поддержки синтаксиса Markdown
import markdown

register = template.Library()

@register.simple_tag
def total_posts():
    return Post.published.count()

# Мы создали простой шаблонный тег, который возвращает число опубли-
# кованных в блоге постов.
# Для того чтобы быть допустимой библиотекой тегов, в каждом содержащем
# шаблонные теги модуле должна быть определена переменная с именем register.
# Эта переменная является экземпляром класса template.Library, и она
# используется для регистрации шаблонных тегов и фильтров приложения.
# В приведенном выше исходном коде тег total_posts был определен с помощью
# простой функции Python. В функцию был добавлен декоратор @register.
# simple_tag, чтобы зарегистрировать ее как простой тег. Django будет
# использовать имя функции в качестве имени тега. Если есть потребность за-
# регистрировать ее под другим именем, то это можно сделать, указав атрибут
# name, например @register.simple_tag(name='my_tag').
# После добавления нового модуля шаблонных тегов потребуется перезапустить
# сервер разработки, чтобы новые теги и фильтры стали доступны для ис-
# пользования в шаблонах.
# Прежде чем использовать конкретно-прикладные шаблонные теги, необ-
# ходимо сделать их доступными для шаблона с помощью
# тега {% load %}. Как
# упоминалось ранее, нужно использовать имя модуля Python, содержащего
# ваши шаблонные теги и фильтры.
# Отредактируйте шаблон blog/templates/base.html, добавив тег {% load blog_
# tags %} в верхней его части, чтобы загрузить свой модуль шаблонных тегов.
# Затем примените созданный вами тег для отображения общего числа постов,
# как показано ниже.

# - - - - - - - - - - - - -
# Создание шаблонного тега включения
# Мы создадим еще один тег, чтобы отображать последние посты на боковой
# панели блога. На этот раз мы реализуем тег включения. Используя тег вклю-
# чения, можно отображать шаблон с контекстными переменными, возвраща-
# емыми вашим шаблонным тегом.
@register.inclusion_tag('blog/post/latest_posts.html')
def show_latest_posts(count=5):
    latest_posts = Post.published.order_by('-publish')[:count]
    return {'latest_posts': latest_posts} 
# В приведенном выше исходном коде мы зарегистрировали шаблонный
# тег, применяя декоратор @register.inclusion_tag. Используя blog/post/latest_
# posts.html, был указан шаблон, который будет прорисовываться воз-
# вращенными значениями. Шаблонный тег будет принимать опциональный
# параметр count, который по умолчанию равен 5. Этот параметр позволит
# задавать число отображаемых постов. Данная переменная используется для
# того, чтобы ограничивать результаты запроса Post.published.order_by('-publish')[:
# count].
# Обратите внимание, что приведенная выше функция возвращает не простое
# значение, а словарь переменных. Теги включения должны возвращать
# словарь значений, который используется в качестве контекста для прорисов-
# ки заданного шаблона. Только созданный шаблонный тег позволяет задавать
# опциональное число отображаемых постов как {% show_latest_posts 3 %}.
# Теперь создайте новый файл шаблона в разделе blog/post/ и назовите его
# latest_posts.html.
# Отредактируйте новый шаблон blog/post/latest_posts.html

# Создание шаблонного тега, возвращающего набор запросов
# Наконец, мы создадим простой шаблонный тег, который возвращает значе-
# ние. Мы сохраним результат в реиспользуемой переменной, не выводя его
# напрямую. Мы создадим тег, чтобы отображать посты с наибольшим числом
# комментариев.
# Отредактируйте файл templatetags/blog_tags.py, добавив следующую ниже
# инструкцию импорта и шаблонный тег:
@register.simple_tag
def get_most_commented_posts(count=5):
    return Post.published.annotate(
                                total_comments=Count('comments')
                                ).order_by('-total_comments')[:count]
# В приведенном выше шаблонном теге с помощью
# функции annotate() формируется набор запросов QuerySet, чтобы агрегировать 
# общее число ком ментариев к каждому посту. Функция агрегирования Count используется для
# сохранения количества комментариев в вычисляемом поле total_comments по
# каждому объекту Post. Набор запросов QuerySet упорядочивается по вычис-
# ляемому полю в убывающем порядке. Также предоставляется опциональная
# переменная count, чтобы ограничивать общее число возвращаемых объектов.
# В дополнение к Count Django предлагает функции агрегирования Avg, Max,
# Min и Sum.
# Далее отредактируйте шаблон blog/base.html

# - - - - - - - - - - - - - - - - - - - - - - - 
# Создание шаблонного фильтра для поддержки синтаксиса Markdown
@register.filter(name='markdown')
def markdown_format(text):
    return mark_safe(markdown.markdown(text))
    #     Шаблонные фильтры регистрируются таким же образом, как и шаблон-
    # ные теги. Во избежание конфликта имен между именем функции и модулем
    # markdown мы дали функции имя markdown_format, а фильтру – имя markdown для
    # использования в шаблонах, в частности {{ variable|markdown }}.
    # Отредактируйте шаблон blog/post/detail.html,